﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using Grain.Crm.DataMigrator.CrmServices;
using Grain.Crm.ExcelExtractor;
using Grain.Crm.ExcelExtractor.Input;
using Grain.Crm.ExcelExtractor.InputDescription;
using Grain.Crm.ExcelExtractor.InputDescription.Sheets;
using Grain.Crm.ExcelImporter;
using Grain.Crm.DataMigrator.Imports;

namespace Grain.Crm.DataMigrator
{
    public class ImportPayloadGenerator
    {
        public static IEnumerable<ImportPayload> GeneratePayload(SheetDescription sheetDescription, EnumerableRowCollection<DataRow> collection, string entityName, string filename)
        {

            if (entityName == EntityName.contact.ToString())
            {
                var contentRow = FileContentHelper.GenerateContentRow(sheetDescription, collection, entityName);
                var headerRow = FileContentHelper.GenerateHeaderRow(sheetDescription, entityName);

                var fullname = GetFullName(sheetDescription, collection);
                //insert 'Full Name':

                var sb = new StringBuilder(contentRow);
                sb.Insert(0, fullname + ",");
                contentRow = sb.ToString();

                sb = new StringBuilder(headerRow);
                sb.Insert(0, "Full Name,");
                headerRow = sb.ToString();

                
                return new[] { new ImportPayload(entityName, contentRow, headerRow, filename) };
            }

            if (entityName == EntityName.new_curriculumvitae.ToString())
            {
                var contentRow = FileContentHelper.GenerateContentRow(sheetDescription, collection, entityName);
                var headerRow = FileContentHelper.GenerateHeaderRow(sheetDescription, entityName);

                var fullname = GetFullName(sheetDescription, collection);

                var sbContent = new StringBuilder(contentRow);
                var sbHeader = new StringBuilder(headerRow);

                sbHeader.Insert(0, "ID, Language");
                sbContent.Insert(0, "CV-TempID," + ImportsGlobal.Language);

                return new[] { new ImportPayload(entityName, sbContent.ToString(), sbHeader.ToString(), filename) };
            }

            if (entityName == EntityName.new_contactlanguage.ToString())
            {
                List<ImportPayload> payloads = new List<ImportPayload>();

                payloads.Add(CreateContactLanguagePayload("Slovak", sheetDescription, collection, filename));
                payloads.Add(CreateContactLanguagePayload("English", sheetDescription, collection, filename));
                payloads.Add(CreateContactLanguagePayload("German", sheetDescription, collection, filename));
                payloads.Add(CreateContactLanguagePayload("French", sheetDescription, collection, filename));
                payloads.Add(CreateContactLanguagePayload("Spanish", sheetDescription, collection, filename));
                payloads.Add(CreateContactLanguagePayload("Russian", sheetDescription, collection, filename));

                return payloads.Where(p => p != null);
            }

            if (entityName == EntityName.new_contactskill.ToString())
            {
                var skillsSheet = sheetDescription as SkillsSheetDescription;
                if (skillsSheet == null)
                    throw new ArgumentException("SheetDescription should be of type SkillsSheetDescription");

                int rowIndex = 1;
                var payloads = new List<ImportPayload>();

                foreach (var row in collection)
                {
                    var skillName = row.GetValue(sheetDescription.Descriptions.GetByXlsValueName("Skill").Column);
                    var skillLevel =
                        row.GetValue(sheetDescription.Descriptions.GetByXlsValueName("SkillLevel").Column);
                    var skillYears =
                        row.GetValue(sheetDescription.Descriptions.GetByXlsValueName("SkillExpYears").Column);
                    var skillArea = row.GetValue(sheetDescription.Descriptions.GetByXlsValueName("Skill Area").Column); //remove the first X. Skill Area
                    var skillSubArea = row.GetValue(sheetDescription.Descriptions.GetByXlsValueName("Skills Sub-Area").Column); //remove the first X. Skill Area

                    if (!string.IsNullOrEmpty(skillLevel) && !string.IsNullOrEmpty(skillYears))
                    {
                        if (rowIndex >= skillsSheet.SkillsStartedAtRow &&
                            !skillLevel.Contains(skillsSheet.IgnoreSkillLevelvalue) &&
                            !skillYears.Contains(skillsSheet.IgnoreSkillMonthsvalue))
                        {
                            const string headerRow = "Name,Skill Area,Skills Sub-Area,Skill,Level,Years of experience";
                            var contentRow = "TempID," + skillArea + "," + skillSubArea.Substring(4) + "," + skillName + "," + skillLevel + "," + skillYears;

                            payloads.Add(new ImportPayload(entityName, contentRow, headerRow, filename));
                        }
                    }

                    rowIndex++;
                }


                return payloads;
            }

            if (entityName == EntityName.new_professionalexperience.ToString())
            {
                var payloads = new List<ImportPayload>();

                var peDesc = sheetDescription as WorkingExperienceSheetDescription;
                
                var headerRow = FileContentHelper.GenerateHeaderRow(sheetDescription, entityName);
                //headerRow += ",Name";

                for (int i = 0; i < peDesc.RecordsCount; i++)
                {
                    var contentRow = FileContentHelper.GenerateContentRow(sheetDescription, collection, entityName, i * peDesc.NextRecordRowDiff);
                    
                    if (contentRow.All(c => c == ',')) continue;

                    //contentRow += ",Professional Experience record nr." + (i+1);

                    payloads.Add(new ImportPayload(entityName, contentRow, headerRow, filename));
                }

                return payloads;
            }
            if(entityName == EntityName.new_contactprojects.ToString())
            {
                var payloads = new List<ImportPayload>();
                var projectDesc = sheetDescription as ProjectExperienceSheetDescription;

                var headerRow = FileContentHelper.GenerateHeaderRow(sheetDescription, entityName);

                for (int i = 0; i < projectDesc.RecordsCount; i++)
                {
                    var contentRow = FileContentHelper.GenerateContentRow(sheetDescription, collection, entityName, i * projectDesc.NextRecordRowDiff);

                    if (contentRow.All(c => c == ',')) continue;

                    if(string.IsNullOrEmpty(contentRow.GetByHeading(headerRow,"Name")))
                    {
                        contentRow = contentRow.RemoveByHeading(headerRow, "Name");
                        contentRow = contentRow.Insert(0, "Project nr." + (i + 1));
                    }

                    payloads.Add(new ImportPayload(entityName, contentRow, headerRow, filename));
                }

                return payloads;
            }

            if (entityName == EntityName.new_contactcourses.ToString())
            {
                var payloads = new List<ImportPayload>();
                var coursesDesc = sheetDescription as CoursesSheetDescription;

                var headerRow = FileContentHelper.GenerateHeaderRow(sheetDescription, entityName);

                for (int i = 0; i < coursesDesc.RecordsCount; i++)
                {
                    var contentRow = FileContentHelper.GenerateContentRow(sheetDescription, collection, entityName, i * coursesDesc.NextRecordRowDiff);

                    if (contentRow.All(c => c == ',')) continue;

                    if (string.IsNullOrEmpty(contentRow.GetByHeading(headerRow, "Name")))
                    {
                        contentRow = contentRow.RemoveByHeading(headerRow, "Name");
                        contentRow = contentRow.Insert(0, "Course nr." + (i + 1));
                    }

                    payloads.Add(new ImportPayload(entityName, contentRow, headerRow, filename));
                }

                return payloads;
            }

            if (entityName == EntityName.new_education.ToString())
            {
                var payloads = new List<ImportPayload>();
                var educationDesc = sheetDescription as EducationSheetDescription;

                var headerRow = FileContentHelper.GenerateHeaderRow(sheetDescription, entityName);
                headerRow += ",Name";

                for (int i = 0; i < educationDesc.RecordsCount; i++)
                {
                    var contentRow = FileContentHelper.GenerateContentRow(sheetDescription, collection, entityName, i * educationDesc.NextRecordRowDiff);

                    if (contentRow.All(c => c == ',')) continue;

                    contentRow += ",Education nr." + (i + 1);

                    payloads.Add(new ImportPayload(entityName, contentRow, headerRow, filename));
                }

                return payloads;
            }

            throw new InvalidOperationException("GeneratePayload(): Not supported entity:" + entityName);
        }

        private static string GetFullName(SheetDescription sheetDescription, EnumerableRowCollection<DataRow> collection)
        {
            if (!(sheetDescription is ProfileSheetDescription))
                throw new InvalidOperationException("The sheet description should be profile sheet description");

            var lastName = XlsValueRetriever.GetValueByDescription(collection, sheetDescription.Descriptions.GetByCrmDisplayName("Last Name"));
            var firstName = XlsValueRetriever.GetValueByDescription(collection, sheetDescription.Descriptions.GetByCrmDisplayName("First Name"));

            return firstName + " " + lastName;
        }

        private static ImportPayload CreateContactLanguagePayload(string language, SheetDescription sheetDescription, EnumerableRowCollection<DataRow> collection, string filename)
        {
            #region Assertions
            var profile = sheetDescription as ProfileSheetDescription;
            if (profile == null)
                throw new ArgumentException("sheetDescription should be of type ProfileSheetDescription");
            #endregion

            string years, lvl, header, content;

            lvl = XlsValueRetriever.GetValueByDescription(collection,
                                                                      profile.Descriptions.GetByXlsValueName(
                                                                          "LanguageAbility" + language + "Level"));
            if (!string.IsNullOrEmpty(lvl))
            {
                years = XlsValueRetriever.GetValueByDescription(collection,
                                                                    profile.Descriptions.GetByXlsValueName(
                                                                        "LanguageAbility" + language + "Years"));

                header = "Language Skill,Language level,Years of experience";
                content = language + "," + lvl + "," + years;

                return new ImportPayload(EntityName.new_contactlanguage.ToString(), content, header, filename);
            }
            else return null;
        }
    }
}
